package com.tang.system.service.impl;

import com.tang.system.entity.SysPermission;
import com.tang.system.entity.SysUser;
import com.tang.system.service.ILoginService;
import com.tang.system.service.ISysRolePermissionService;
import com.tang.system.service.ISysUserService;
import com.tang.system.vo.LoginVo;
import com.tang.system.vo.SysPermissionTree;
import com.tang.system.vo.UserInfo;
import com.tang.utils.CommonUtils;
import com.tang.utils.LazyAutowired;
import com.tang.utils.LoginUtils;
import com.tang.utils.TreeUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {

    @Autowired
    ISysUserService userService;

    @Autowired
    RedisTemplate redisTemplate;

    @LazyAutowired
    ISysRolePermissionService sysRolePermissionService;

    @Override
    public Object login(LoginVo user) {
        List<SysUser> sysUsers = checkUserLoginParams(user);
        SysUser sysUser = sysUsers.get(0);

        String token = LoginUtils.createLoginToken(sysUser);
        clearOtherLoginCache(sysUser);
        UserInfo userInfo = createUserInfo(user, sysUser, token);
        saveToCache(token, userInfo);
        return userInfo;
    }

    private void clearOtherLoginCache(SysUser sysUser) {
        Set keys = redisTemplate.keys(sysUser.getUsername() + "$$*");
        if (CommonUtils.isEmpty(keys)) return ;
        for (Object key : keys) {
            redisTemplate.delete(key);
        }
    }

    private void saveToCache(String token, UserInfo userInfo) {
        redisTemplate.opsForValue().set(token, userInfo, 30, TimeUnit.MINUTES);
    }

    private UserInfo createUserInfo(LoginVo user, SysUser sysUser, String token) {
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(sysUser, userInfo);
        userInfo.setToken(token);
        loadPermisstions(userInfo);
        return userInfo;
    }

    @Override
    public void loadPermisstions(UserInfo userInfo) {
        Long id = userInfo.getId();
        List<SysPermission> userPermissions = sysRolePermissionService.getUserPermissions(id);
        if (CommonUtils.isEmpty(userPermissions)) return;
        List<SysPermissionTree> sysPermissionTrees = CommonUtils.copyToList(userPermissions, SysPermissionTree.class);
        List<SysPermissionTree> permissionTrees = TreeUtils.toList(sysPermissionTrees, SysPermissionTree::getId, SysPermissionTree::getParentId, SysPermissionTree::getChildren);
        userInfo.setPermissions(permissionTrees);
    }

    private List<SysUser> checkUserLoginParams(LoginVo user) {
        CommonUtils.isEmptyThrow(user.getUsername(), new RuntimeException("用户名不能为空"));
        CommonUtils.isEmptyThrow(user.getPassword(), new RuntimeException("密码不能为空"));
        List<SysUser> sysUsers = userService.lambdaQuery()
                .eq(SysUser::getActive, true)
                .eq(SysUser::getUsername, user.getUsername()).list();
        if (CommonUtils.isEmpty(sysUsers)) throw new RuntimeException("用户名或密码有误!");
        if (!LoginUtils.checkPassWord(user.getPassword(), sysUsers.get(0))) {
            throw new RuntimeException("用户名或密码有误!");
        }
        return sysUsers;
    }
}
